package com.wntime.simulator.device;

import com.ghgande.j2mod.modbus.procimg.SimpleProcessImage;
import com.ghgande.j2mod.modbus.procimg.SimpleRegister;
import com.ghgande.j2mod.modbus.slave.ModbusSlave;
import com.ghgande.j2mod.modbus.slave.ModbusSlaveFactory;
import com.wntime.simulator.device.register.AccumulateSimpleRegister;
import com.wntime.simulator.device.register.RangeSimpleRegister;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

@Slf4j
public class ModbusDevice {
    private ModbusSlave slave;
    private boolean isRunning = true;

    @Getter
    private final Simulator simulator;

    private SimpleProcessImage spi;

    public ModbusDevice(Simulator simulator) {
        this.simulator = simulator;
    }

    public void initial() {
        this.spi = new SimpleProcessImage();
    }

    public void start() throws Exception {
        //this.spi = new SimpleProcessImage();
        Boolean overTcp = simulator.getOverTcp();
        this.slave = ModbusSlaveFactory.createTCPSlave(simulator.getPort(), simulator.getPoolSize() * 10, overTcp);
        slave.addProcessImage(simulator.getUintId(), spi);
        slave.open();
        if (overTcp) {
            log.info("Modbus [{}]:{} Over TCP Slave is running...", simulator.getId(), simulator.getName());
        } else {
            log.info("Modbus [{}]:{} TCP Slave is running...", simulator.getId(), simulator.getName());
        }
        this.isRunning = true;
//        spi.addRegister(100,new RangeSimpleRegister(100,200));
//        spi.addRegister(101,new AccumulateSimpleRegister(100,10));// 设置 Modbus 从机
//        ModbusSlave slave =  ModbusSlaveFactory.createTCPSlave(502, 1,true);
//        ModbusSlave slave2 =  ModbusSlaveFactory.createTCPSlave(503, 1,false);
//        slave1.addProcessImage(1, spi);
//        slave1.open();
//        spi.addRegister(103,new RangeSimpleRegister(100,200));
//        spi.addRegister(104,new AccumulateSimpleRegister(100,2));

//        slave2.addProcessImage(2, spi);
//        slave2.open();
    }

    public void setSpi(List<SimulationField> fields) {
        for (SimulationField field : fields) {
            if (field.getChange().startsWith("range")) {
                this.spi.addRegister(field.getRef(), new RangeSimpleRegister(field));
            } else if (field.getChange().startsWith("acc")) {
                this.spi.addRegister(field.getRef(), new AccumulateSimpleRegister(field));
            } else {
                this.spi.addRegister(field.getRef(), new SimpleRegister(field.getAfter()));
            }
        }
        log.info("初始化 {} 个模拟字段", fields.size());
    }

    public void stop() {
        ModbusSlaveFactory.close(slave);
        this.isRunning = false;
        log.info("Modbus [{}]:{} Stopped.", simulator.getId(), simulator.getName());
    }

    public void open() {
        try {
            this.start();
            log.info("Modbus [{}]:{} Opened.", simulator.getId(), simulator.getName());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public int status() {
        return this.isRunning ? 0 : 1;
    }
}
